package featuresWindows;

import helpFeaturesWindows.HelpSlotWindow;
import j3d.J3D;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import CAD.MainFrame;

import operationSolids.CSGSolid;
import operationSolids.CompoundSolid;

import features.Block;
import features.Feature;
import features.LinearProfile;

import visualCAD.SlotWindow;
import visualCAD.holeWindowView;
public class CreateSlot extends SlotWindow implements ActionListener{

	private J3D j3d = null;
	private SlotDinamicTopPanel slotTopPanel;
	private SlotDinamicBottomPanel slotBottomPanel;
	Double angle=0.0;
	double positionX = 0,
	positionY = 0, 
	positionZ = 0,
	d1 = 0, 
	d2 = 0, 
	depth = 0;
	public CreateSlot(J3D j3d, Block block)
	{
		super();
		setVisible(true);
		pack();
		slotSplitPanel.setDividerLocation(0.5);
		slotSplitPanel.setTopComponent(slotTopPanel=new SlotDinamicTopPanel(positionX,positionY,d1,d2,angle));
		slotSplitPanel.setBottomComponent(slotBottomPanel=new SlotDinamicBottomPanel(positionX,positionZ,d1,d2,depth,angle));
		this.j3d = j3d;
		this.init();
		
	}
	public J3D getJ3d() {
		return j3d;
	}
	public void setJ3d(J3D j3d) {
		this.j3d = j3d;
	}
	public SlotDinamicTopPanel getSlotTopPanel() {
		return slotTopPanel;
	}
	public void setSlotTopPanel(SlotDinamicTopPanel slotTopPanel) {
		this.slotTopPanel = slotTopPanel;
	}
	public SlotDinamicBottomPanel getSlotBottomPanel() {
		return slotBottomPanel;
	}
	public void setSlotBottomPanel(SlotDinamicBottomPanel slotBottomPanel) {
		this.slotBottomPanel = slotBottomPanel;
	}
	public Double getAngle() {
		return angle;
	}
	public void setAngle(Double angle) {
		this.angle = angle;
	}
	public double getPositionX() {
		return positionX;
	}
	public void setPositionX(double positionX) {
		this.positionX = positionX;
	}
	public double getPositionY() {
		return positionY;
	}
	public void setPositionY(double positionY) {
		this.positionY = positionY;
	}
	public double getPositionZ() {
		return positionZ;
	}
	public void setPositionZ(double positionZ) {
		this.positionZ = positionZ;
	}
	public double getD1() {
		return d1;
	}
	public void setD1(double d1) {
		this.d1 = d1;
	}
	public double getD2() {
		return d2;
	}
	public void setD2(double d2) {
		this.d2 = d2;
	}
	public double getDepth() {
		return depth;
	}
	public void setDepth(double depth) {
		this.depth = depth;
	}
	public void init()
	{
		double y = slotTopPanel.faceY;
		double x = slotTopPanel.faceX;
		double z = slotTopPanel.faceZ;
		helpButton.addActionListener(this);
		SpinnerModel zModel = new SpinnerNumberModel(0.0,-z, 0.0, 0.1);
		SpinnerModel yModel = new SpinnerNumberModel(0.0,0.0, y, 0.1);
		SpinnerModel xModel = new SpinnerNumberModel(0.0,0.0, x, 0.1);
		SpinnerModel depthModel = new SpinnerNumberModel(0.0,0.0, z, 0.1);
		SpinnerModel d1Model = new SpinnerNumberModel(0.0,0.0, null, 0.1);
		SpinnerModel d2Model = new SpinnerNumberModel(0.0,0.0, null, 0.1);
		d1SlotSpinner.setModel(d1Model);
		d2SlotSpinner.setModel(d2Model);
		zSlotSpinner.setModel(zModel);
		xSlotSpinner.setModel(xModel);
		ySlotSpinner.setModel(yModel);
		depthSlotSpinner.setModel(depthModel);
		
		this.d1SlotSpinner.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				redrawDynamicBoxes();
			}
		});
		this.d2SlotSpinner.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				redrawDynamicBoxes();
			}
		});
		ySlotSpinner.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				redrawDynamicBoxes();
			}
		});
		zSlotSpinner.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				redrawDynamicBoxes();
			}
		});
		xSlotSpinner.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				redrawDynamicBoxes();
			}
		});
		depthSlotSpinner.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				redrawDynamicBoxes();
			}
		});
		rotationSpinner.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				redrawDynamicBoxes();
			}
		});
		
		
		
		this.submitButton.addActionListener(this);
		this.cancelButton.addActionListener(this);
		this.setResizable(false);
	}
	private void redrawDynamicBoxes(){
		try{
			d1=(Double)d1SlotSpinner.getValue();
			d2=(Double)d2SlotSpinner.getValue();
			positionX=(Double)xSlotSpinner.getValue();
			positionY=(Double)ySlotSpinner.getValue();
			positionZ=(Double)zSlotSpinner.getValue();
			depth=(Double)depthSlotSpinner.getValue();
			angle = (Double)rotationSpinner.getValue();
			}
			catch (Exception e1) {
				JOptionPane.showMessageDialog(null, "error in entering data");
			}
			slotSplitPanel.setTopComponent(slotTopPanel=new SlotDinamicTopPanel(positionX,positionY,d1,d2,angle));
			slotSplitPanel.setBottomComponent(slotBottomPanel=new SlotDinamicBottomPanel(positionX,positionZ,d1,d2,depth,angle));
			slotSplitPanel.setDividerLocation(0.5);
	}
	public void actionPerformed(ActionEvent evt) {
		Object origin = evt.getSource();
		
		
		if (origin.equals(this.submitButton))
		{
			this.ok();
		}
		else if (origin.equals(this.cancelButton))
		{
			this.cancel();
		}
		else if (origin.equals(this.helpButton))
		{
			new HelpSlotWindow();
		}
	}
	private void cancel()
	{
		// TODO Auto-generated method stub
		this.dispose();
	}
	private void ok() 
	{
		// TODO Auto-generated method stub
		boolean ok = true;
	
		//----------- positionX validation -----------//
		
		if (ok)
		{
			try
			{
				positionX = (Double)this.xSlotSpinner.getValue();
			
			}
			catch (Exception e)
			{
				JOptionPane.showMessageDialog(null, "error in entering data");
				ok = false;
			}
		}
		//------------- positionY validation ------------//
		if (ok)
		{
			try
			{
				positionZ = -(Double)this.ySlotSpinner.getValue();
			}
			catch (Exception e)
			{
				JOptionPane.showMessageDialog(null, "error in entering data");
				ok = false;
			}
		}
		//------------- positionZ validation -------------//
		if (ok)
		{
			try
			{
				positionY = (Double)this.zSlotSpinner.getValue();
			}
			catch (Exception e)
			{
				JOptionPane.showMessageDialog(null, "error in entering data");
				ok = false;
			}
		}
		//-------------- radius Validation ---------------//
		if (ok)
		{
			try
			{
				depth = (Double)this.depthSlotSpinner.getValue();
			}
			catch (Exception e)
			{
				JOptionPane.showMessageDialog(null, "error in entering data");
				ok = false;
			}
		}
		//-------------- depth Validation ---------------//
		if (ok)
		{
			try
			{
				d1 = (Double)this.d1SlotSpinner.getValue();
			}
			catch (Exception e)
			{
				JOptionPane.showMessageDialog(null, "error in entering data");
				ok = false;
			}
		}
		//-------------- length Validation ---------------//
		if (ok)
		{
			try
			{
				d2 = (Double)this.d2SlotSpinner.getValue();
			}
			catch (Exception e)
			{
				JOptionPane.showMessageDialog(null, "error in entering data");
				ok = false;
			}
		}
		if(ok){
		LinearProfile st = new LinearProfile(Feature.LINEARPROFILE,
				null,
				d1,d2,
				(float)positionX,(float)positionZ,(float)positionY,
				depth,
				this.nameTextField.getText(),
				Math.toRadians(angle),MainFrame.Face);
		
		this.j3d.removeSolid();
		this.j3d.addSolid(MainFrame.block.block);
		this.dispose();
		}
	}
	
class SlotDinamicTopPanel extends JComponent{
		
		Shape smallBox;
		Shape bigBox;
		Shape axisX, axisY;
		double faceX = 0;
		double faceY = 0;
		double faceZ = 0;
		double multiplier= 0;
		double angle=0;
		
		
		private void findXandY() {
			switch(MainFrame.Face){
			case MainFrame.TOPFACE:
				faceX = MainFrame.block.width;
				faceY = MainFrame.block.length;
				faceZ = MainFrame.block.height;
				break;
			case MainFrame.LOWERFACE:
				faceX = MainFrame.block.width;
				faceY = MainFrame.block.length;
				faceZ = MainFrame.block.height;
				break;
			case MainFrame.FRONTFACE:
				faceX = MainFrame.block.width;
				faceY = MainFrame.block.height;
				faceZ = MainFrame.block.length;
				break;
			case MainFrame.BACKFACE:
				faceX = MainFrame.block.width;
				faceY = MainFrame.block.height;
				faceZ = MainFrame.block.length;
				break;
			case MainFrame.EASTFACE:
				faceX = MainFrame.block.length;
				faceY = MainFrame.block.height;
				faceZ = MainFrame.block.width;
				break;
			case MainFrame.WESTFACE:
				faceX = MainFrame.block.length;
				faceY = MainFrame.block.height;
				faceZ = MainFrame.block.width;
				break;
			}
		}
		private double calculateMultiplier() {
			double multiplier = 195/faceY;
			if(faceX*multiplier > 310){
				multiplier = 310/faceX;
			}
			if(faceZ*multiplier > 180){
				multiplier = 180/faceZ;
			}
			return multiplier;
		}
		public SlotDinamicTopPanel(double positionX, double positionY, double d1, double d2,double angle) {
			super();
			this.angle=angle;
			findXandY();
			multiplier = calculateMultiplier();
			smallBox=createBox(multiplier*(positionX-(d1/2)),multiplier*(positionY-(d2/2)),multiplier*(d1),multiplier*(d2));
			bigBox=createRectangle();
			axisX = verticalLine();
			axisY = horizontalLine();
		}
		protected Shape createBox(double posX,double posY, double d1, double d2) {
			Shape rectangle = new Rectangle2D.Double(-d1/2,-d2/2, d1, d2);
			AffineTransform at = AffineTransform.getRotateInstance(Math.toRadians(angle));
			rectangle=at.createTransformedShape(rectangle);
			rectangle=translate(rectangle,10+posX+d1/2,+d2/2+20+posY);
			return rectangle;

		}
		protected Shape createRectangle() {
			Shape rectangle = new Rectangle2D.Double(10,20,faceX*multiplier,faceY*multiplier);
			return rectangle;
		}
		protected Shape verticalLine() {
			
			Shape axisY = new Line2D.Double(10, 20, 10, 50);
			return axisY;
		}
		protected Shape horizontalLine(){
			Shape axisX = new Line2D.Double(10, 20, 50, 20);
			return axisX;
		}
		protected Shape translate(Shape shape,double dx,double dy){
			AffineTransform at = AffineTransform.getTranslateInstance(dx, dy);
			return at.createTransformedShape(shape);
		}
		
		
		public void paint(Graphics g) {
			//System.out.println("translateY = " + translateY);
			Graphics2D g2 = (Graphics2D) g;
			g2.scale(1, -1);
			g2.translate(0, -215);
			g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
			g2.setPaint(new Color(211, 211, 211));
			g2.fill(bigBox);
			g2.setPaint(new Color(135, 206, 250));
			g2.fill(smallBox);
			g2.setPaint(Color.BLUE);
			g2.draw(smallBox);
			g2.setPaint(Color.BLACK);
			g2.draw(bigBox);
			g2.setPaint(Color.RED);
			g2.draw(axisX);
			g2.draw(axisY);
			g2.scale(1, -1);
			g2.drawString("X", 50 ,-10);
			g2.drawString("Y", 0, -50);
		}
	}



class SlotDinamicBottomPanel extends JComponent{
	
	Shape smallBox;
	Shape bigBox;
	Shape axisX, axisY;
	double faceX = 0;
	double faceY = 0;
	double faceZ = 0;
	double multiplier= 0;
	
	
	private void findXandY() {
		switch(MainFrame.Face){
		case MainFrame.TOPFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.length;
			faceZ = MainFrame.block.height;
			break;
		case MainFrame.LOWERFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.length;
			faceZ = MainFrame.block.height;
			break;
		case MainFrame.FRONTFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.length;
			break;
		case MainFrame.BACKFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.length;
			break;
		case MainFrame.EASTFACE:
			faceX = MainFrame.block.length;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.width;
			break;
		case MainFrame.WESTFACE:
			faceX = MainFrame.block.length;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.width;
			break;
		}
	}
	private double calculateMultiplier() {
		double multiplier = 195/faceY;
		if(faceX*multiplier > 310){
			multiplier = 310/faceX;
		}
		if(faceZ*multiplier > 180){
			multiplier = 180/faceZ;
		}
		return multiplier;
	}
	
	public SlotDinamicBottomPanel(double positionX, double positionZ, double d1,double d2, double depth,double angle) {
		super();
		findXandY();
		multiplier = calculateMultiplier();
		smallBox=createBox(multiplier*(positionX-(d1/2)),multiplier*(-positionZ),multiplier*(d1),multiplier*(depth),multiplier*(d2),angle);
		bigBox=createRectangle();
		axisX = verticalLine();
		axisY = horizontalLine();
	}
	protected Shape createBox(double posX,double posY, double d1, double d2,double d3, double angle) {
		Shape rectangle = new Rectangle2D.Double(10+posX-
				(Math.abs(d1*Math.cos(Math.toRadians(angle)))+
				Math.abs(d3*Math.sin(Math.toRadians(angle)))-d1)/2,
				20+posY,
				Math.abs(d1*Math.cos(Math.toRadians(angle)))+
				Math.abs(d3*Math.sin(Math.toRadians(angle))), d2);
		return rectangle;
	}
	protected Shape createRectangle() {
		Shape rectangle = new Rectangle2D.Double(10,20,faceX*multiplier,faceZ*multiplier);
		return rectangle;
	}
	protected Shape verticalLine() {
		
		Shape axisY = new Line2D.Double(10, 20, 10, 50);
		return axisY;
	}
	protected Shape horizontalLine(){
		Shape axisX = new Line2D.Double(10, 20, 50, 20);
		return axisX;
	}
	
	
	public void paint(Graphics g) {
		//System.out.println("translateY = " + translateY);
		Graphics2D g2 = (Graphics2D) g;
		g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
		float dash1[] = {2.5f, 2.5f};
		
		g2.setPaint(new Color(211, 211, 211));
		g2.fill(bigBox);
		g2.setPaint(new Color(135, 206, 250));
		g2.fill(smallBox);
		g2.setPaint(Color.BLUE);
		g2.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_BUTT, 
				BasicStroke.JOIN_MITER, 10.0f, dash1, 0.0f));
		g2.draw(smallBox);
		g2.setPaint(Color.BLACK);
		g2.setStroke(new BasicStroke());
		g2.draw(bigBox);
		g2.setPaint(Color.RED);
		g2.draw(axisX);
		g2.draw(axisY);
		g2.drawString("X", 50 ,20);
		g2.drawString("-Z", 0, 50);
	}
}
}
